using Microsoft.Expression.Drawing.Core;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
namespace Microsoft.Expression.Media
{
	internal class LineArrowGeometrySource : GeometrySource<ILineArrowGeometrySourceParameters>
	{
		protected override bool UpdateCachedGeometry(ILineArrowGeometrySourceParameters parameters)
		{
			PathGeometry pathGeometry;
			bool flag = false | GeometryHelper.EnsureGeometryType<PathGeometry>(out pathGeometry, ref this.cachedGeometry, () => new PathGeometry()) | pathGeometry.get_Figures().EnsureListCount(3, () => new PathFigure());
			Point startPoint = this.GetStartPoint(parameters);
			Point endPoint = this.GetEndPoint(parameters);
			Point middlePoint = this.GetMiddlePoint(parameters);
			PathFigure pathFigure = pathGeometry.get_Figures().get_Item(0);
			QuadraticBezierSegment dependencyObject;
			flag = (flag | pathFigure.SetIfDifferent(PathFigure.StartPointProperty, startPoint) | pathFigure.SetIfDifferent(PathFigure.IsClosedProperty, false) | pathFigure.SetIfDifferent(PathFigure.IsFilledProperty, false) | pathFigure.get_Segments().EnsureListCount(1, () => new QuadraticBezierSegment()) | GeometryHelper.EnsureSegmentType<QuadraticBezierSegment>(out dependencyObject, pathFigure.get_Segments(), 0, () => new QuadraticBezierSegment()) | dependencyObject.SetIfDifferent(QuadraticBezierSegment.Point1Property, middlePoint) | dependencyObject.SetIfDifferent(QuadraticBezierSegment.Point2Property, endPoint) | LineArrowGeometrySource.UpdateArrow(parameters.StartArrow, parameters.ArrowSize, pathGeometry.get_Figures().get_Item(1), startPoint, startPoint.Subtract(middlePoint).Normalized()) | LineArrowGeometrySource.UpdateArrow(parameters.EndArrow, parameters.ArrowSize, pathGeometry.get_Figures().get_Item(2), endPoint, endPoint.Subtract(middlePoint).Normalized()));
			return true;
		}
		private static bool UpdateArrow(ArrowType arrowType, double size, PathFigure figure, Point startPoint, Vector tangent)
		{
			bool flag = false;
			switch (arrowType)
			{
			case ArrowType.NoArrow:
				flag = (flag | figure.SetIfDifferent(PathFigure.StartPointProperty, startPoint) | figure.get_Segments().EnsureListCount(0, null));
				return flag;
			case ArrowType.OvalArrow:
			{
				Rect bounds = new Rect(startPoint.get_X() - size / 2.0, startPoint.get_Y() - size / 2.0, size, size);
				flag |= PathFigureHelper.SyncEllipseFigure(figure, bounds, 1, true);
				return flag;
			}
			}
			Point[] pointTrio = LineArrowGeometrySource.GetPointTrio(startPoint, tangent, size);
			if (arrowType == ArrowType.StealthArrow)
			{
				List<Point> list = new List<Point>(pointTrio);
				list.Add(startPoint - tangent * size * 2.0 / 3.0);
				flag |= PathFigureHelper.SyncPolylineFigure(figure, list, true, true);
			}
			else
			{
				bool flag2 = arrowType == ArrowType.OpenArrow;
				flag |= PathFigureHelper.SyncPolylineFigure(figure, pointTrio, !flag2, !flag2);
			}
			return flag;
		}
		private static Point[] GetPointTrio(Point startPoint, Vector tangent, double size)
		{
			Vector vector = tangent.Perpendicular().Normalized() * 0.57735;
			return new Point[]
			{
				startPoint - tangent * size + vector * size,
				startPoint,
				startPoint - tangent * size - vector * size
			};
		}
		private Point GetMiddlePoint(ILineArrowGeometrySourceParameters parameters)
		{
			Rect logicalBounds = base.LogicalBounds;
			double alpha = (parameters.BendAmount + 1.0) / 2.0;
			switch (parameters.StartCorner)
			{
			case CornerType.TopLeft:
				return GeometryHelper.Lerp(logicalBounds.BottomLeft(), logicalBounds.TopRight(), alpha);
			case CornerType.TopRight:
				return GeometryHelper.Lerp(logicalBounds.TopLeft(), logicalBounds.BottomRight(), alpha);
			case CornerType.BottomRight:
				return GeometryHelper.Lerp(logicalBounds.TopRight(), logicalBounds.BottomLeft(), alpha);
			case CornerType.BottomLeft:
				return GeometryHelper.Lerp(logicalBounds.BottomRight(), logicalBounds.TopLeft(), alpha);
			default:
				return logicalBounds.Center();
			}
		}
		private Point GetEndPoint(ILineArrowGeometrySourceParameters parameters)
		{
			Rect logicalBounds = base.LogicalBounds;
			switch (parameters.StartCorner)
			{
			case CornerType.TopLeft:
				return logicalBounds.BottomRight();
			case CornerType.TopRight:
				return logicalBounds.BottomLeft();
			case CornerType.BottomRight:
				return logicalBounds.TopLeft();
			case CornerType.BottomLeft:
				return logicalBounds.TopRight();
			default:
				return logicalBounds.BottomRight();
			}
		}
		private Point GetStartPoint(ILineArrowGeometrySourceParameters parameters)
		{
			Rect logicalBounds = base.LogicalBounds;
			switch (parameters.StartCorner)
			{
			case CornerType.TopLeft:
				return logicalBounds.TopLeft();
			case CornerType.TopRight:
				return logicalBounds.TopRight();
			case CornerType.BottomRight:
				return logicalBounds.BottomRight();
			case CornerType.BottomLeft:
				return logicalBounds.BottomLeft();
			default:
				return logicalBounds.BottomRight();
			}
		}
	}
}
